<script setup lang="ts">
import { ref, onMounted, watch } from 'vue'
import ace from 'ace-builds'
import 'ace-builds/src-noconflict/mode-javascript'
import 'ace-builds/src-noconflict/theme-monokai'
import 'ace-builds/src-noconflict/keybinding-vim'

const props = defineProps<{
  modelValue: string
}>()

const emit = defineEmits<{
  (e: 'update:modelValue', value: string): void
}>()

const editorRef = ref<HTMLElement | null>(null)
const vimMode = ref(false)
let editor: any = null

onMounted(() => {
  if (editorRef.value) {
    // 初始化ACE编辑器
    editor = ace.edit(editorRef.value, {
      minLines: 40,
      maxLines: 40,
      theme: 'ace/theme/monokai',
      mode: 'ace/mode/javascript',
      fontSize: '16px',
      fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace',
      value: props.modelValue,
      keyBinding: "ace/keyboard/vim"
    })

    editor.container.style.lineHeight = '1.2';
    editor.renderer.setScrollMargin(10, 10, 5, 5);

    editor.on('change', () => {
      emit('update:modelValue', editor.getValue())
    })
  }
})

watch(() => props.modelValue, (newValue) => {
  if (editor && newValue !== editor.getValue()) {
    editor.setValue(newValue, -1)
  }
})

watch(vimMode, (newValue) => {
  if (editor) {
    if (newValue) {
      editor.setKeyboardHandler("ace/keyboard/vim");

      var event = new KeyboardEvent('keypress', {
        keyCode: 27,
        which: 27
      });

      editor.textInput.getElement().dispatchEvent(event);
    } else {
      editor.setKeyboardHandler(null);
    }
  }
})
</script>

<template>
  <div class="code-editor">
    <div ref="editorRef" class="editor-container"></div>
  </div>
  <div class="editor-setting">
    <input type="checkbox" id="vim-mode" v-model="vimMode" />
    <label for="vim-mode">Vim 模式</label>
  </div>
</template>

<style scoped>
.editor-container {
  border-radius: 8px 8px 0 0;
}

.editor-setting {
  background-color: black;
  border-radius: 0 0 8px 8px;
}

.editor-setting input {
  margin-left: 5px;
}
</style>